/********************************************************************************/
/* Projekt EBike_02                                                             */
/* Autor:   Gerhard Woelfl                                                      */
/* Datum:   29.05.2014                                                          */
/* Changes: 29.05.2014: Initial Version                                         */
/*                                                                              */
/********************************************************************************/

#include <xc.h>
#include "init.h"
#include "adc.h"
// #include "spi.h"
#include "i2c_slavedrv.h"                       //Include file for I2C1 Driver
#include "logger.h"
#include "sin.h"
#include "timer.h"
#include "mc.h"
#include "system_const.h"



// *** Chip Configuration ******************************************************
// ICD Communication Channel Select bits
// ICS = NONE	 Reserved, do not use
// ICS = PGD3	 Communicate on PGEC3 and PGED3
// ICS = PGD2	 Communicate on PGEC2 and PGED2
// ICS = PGD1	 Communicate on PGEC1 and PGED1
#pragma config ICS = PGD1

// JTAG Enable bit
// JTAGEN = OFF	 JTAG is disabled
// JTAGEN = ON	 JTAG is enabled
#pragma config JTAGEN = OFF

// Alternate I2C1 pins
// ALTI2C1 = ON	 I2C1 mapped to ASDA1/ASCL1 pins
// ALTI2C1 = OFF	 I2C1 mapped to SDA1/SCL1 pins
#pragma config ALTI2C1 = OFF

// Alternate I2C2 pins
// ALTI2C2 = ON	 I2C2 mapped to ASDA2/ASCL2 pins
// ALTI2C2 = OFF	 I2C2 mapped to SDA2/SCL2 pins
#pragma config ALTI2C2 = ON

// Watchdog Window Select bits
// WDTWIN = WIN75	 WDT Window is 75% of WDT period
// WDTWIN = WIN50	 WDT Window is 50% of WDT period
// WDTWIN = WIN37	 WDT Window is 37.5% of WDT period
// WDTWIN = WIN25	 WDT Window is 25% of WDT period
#pragma config WDTWIN = WIN75

// Watchdog Timer Postscaler bits
// WDTPOST = PS1	 1 : 1
// WDTPOST = PS2	 1 : 2
// WDTPOST = PS4	 1 : 4
// WDTPOST = PS8	 1 : 8
// WDTPOST = PS16	 1 : 16
// WDTPOST = PS32	 1 : 32
// WDTPOST = PS64	 1 : 64
// WDTPOST = PS128	 1 : 128
// WDTPOST = PS256	 1 : 256
// WDTPOST = PS512	 1 : 512
// WDTPOST = PS1024	 1 : 1,024
// WDTPOST = PS2048	 1 : 2,048
// WDTPOST = PS4096	 1 : 4,096
// WDTPOST = PS8192	 1 : 8,192
// WDTPOST = PS16384	 1 : 16,384
// WDTPOST = PS32768	 1 : 32,768
#pragma config WDTPOST = PS16

// Watchdog Timer Prescaler bit
// WDTPRE = PR32	 1 : 32
// WDTPRE = PR128	 1 : 128
#pragma config WDTPRE = PR128

// PLL Lock Enable bit
// PLLKEN = OFF	 Clock switch will not wait for the PLL lock signal.
// PLLKEN = ON	 Clock switch to PLL source will wait until the PLL lock signal is valid.
#pragma config PLLKEN = ON

// Watchdog Timer Window Enable bit
// WINDIS = ON	 Watchdog Timer in Window mode
// WINDIS = OFF	 Watchdog Timer in Non-Window mode
#pragma config WINDIS = OFF

// Watchdog Timer Enable bit
// FWDTEN = OFF	 Watchdog timer enabled/disabled by user software
// FWDTEN = ON	 Watchdog timer always enabled
#pragma config FWDTEN = OFF

// Primary Oscillator Mode Select bits
// POSCMD = EC	 EC (External Clock) Mode
// POSCMD = XT	 XT Crystal Oscillator Mode
// POSCMD = HS	 HS Crystal Oscillator Mode
// POSCMD = NONE	 Primary Oscillator disabled
#pragma config POSCMD = NONE

// OSC2 Pin Function bit
// OSCIOFNC = ON	 OSC2 is general purpose digital I/O pin
// OSCIOFNC = OFF	 OSC2 is clock output
#pragma config OSCIOFNC = ON

// Peripheral pin select configuration
// IOL1WAY = OFF	 Allow multiple reconfigurations
// IOL1WAY = ON	 Allow only one reconfiguration
#pragma config IOL1WAY = OFF

// Clock Switching Mode bits
// FCKSM = CSECME	 Both Clock switching and Fail-safe Clock Monitor are enabled
// FCKSM = CSECMD	 Clock switching is enabled,Fail-safe Clock Monitor is disabled
// FCKSM = CSDCMD	 Both Clock switching and Fail-safe Clock Monitor are disabled
#pragma config FCKSM = CSECMD

// Oscillator Source Selection
// FNOSC = FRC	 Internal Fast RC (FRC)
// FNOSC = FRCPLL	 Fast RC Oscillator with divide-by-N with PLL module (FRCPLL)
// FNOSC = PRI	 Primary Oscillator (XT, HS, EC)
// FNOSC = PRIPLL	 Primary Oscillator with PLL module (XT + PLL, HS + PLL, EC + PLL)
// FNOSC = LPRC	 Low-Power RC Oscillator (LPRC)
// FNOSC = FRCDIVN	 Internal Fast RC (FRC) Oscillator with postscaler
#pragma config FNOSC = FRC

// PWM Lock Enable bit
// PWMLOCK = OFF	 PWM registers may be written without key sequence
// PWMLOCK = ON	 Certain PWM registers may only be written after key sequence
#pragma config PWMLOCK = OFF

// Two-speed Oscillator Start-up Enable bit
// IESO = OFF	 Start up with user-selected oscillator source
// IESO = ON	 Start up device with FRC, then switch to user-selected oscillator source
#pragma config IESO = OFF

// General Segment Write-Protect bit
// GWRP = ON	 General Segment is write protected
// GWRP = OFF	 General Segment may be written
#pragma config GWRP = OFF

// General Segment Code-Protect bit
// GCP = ON	 General Segment Code protection Enabled
// GCP = OFF	 General Segment Code protect is Disabled
#pragma config GCP = OFF

// ****************************************************************************
// Variables
// ****************************************************************************
uint16_t adcIntCnt = 0;
uint8_t msFlag1;
uint16_t msCnt10 = 0;
uint8_t msFlag10;
uint16_t msCnt100 = 0;
uint8_t msFlag100;
uint16_t msCnt1000 = 0;
uint8_t msFlag1000;

uint16_t hallsimcnt = 0;
#define HALL_SIM_MAX_CNT 10


// ****************************************************************************
// Interrupt Routines
// ****************************************************************************

// void _ISR _AD1Interrupt(void)

void __attribute__((__interrupt__, __auto_psv__)) _AD1Interrupt(void) {
    // LATCbits.LATC5 = 1;
    // LATCbits.LATC5 = ~LATCbits.LATC5;
    adcIntCnt++;
    getAdcVals();
    getAngle();
    mcCtrl();
    logger();
    // LATCbits.LATC5 = 0;

    // Clear ADC1 interrupt flag
    IFS0bits.AD1IF = 0;
}

void __attribute__((__interrupt__, __auto_psv__)) _T2Interrupt(void) {
    // LATCbits.LATC5 = ~LATCbits.LATC5;
    t2OvlCnt++;

    // LATCbits.LATC5 = ~LATCbits.LATC5;


    IFS0bits.T2IF = 0;
    ; //Clear Timer2 interrupt flag
}

// Change Notification interrupt (Hall)

void __attribute__((__interrupt__, __auto_psv__)) _CNInterrupt(void) {
    // get sector and speed values
    getSpeedVals();

    IFS1bits.CNIF = 0; // Clear CN interrupt
}

/******************************************************************************/

int dmci_test_01;
uint16_t i;

uint32_t ledCnt = 0;

int main() {
    CPUInit();
    SystemClocks();
    portInit();
    I2C1_Init();
    // SPIInit();
    mcInit();
    i2cMonitorInit();
    loggerInit();
    timerInit();
    PWMInit();
    ADCInit();
    getAdcOfs();
    PWMStart();

    // DEBUG
    // Ende DEBUG
    while (1) {

        // DEBUG
        // mcCtrl();
        // Ende DEBUG

        if (adcIntCnt > 25) {
            // LATCbits.LATC5 = ~LATCbits.LATC5;
            // LED = 1;
            msFlag1 = 1;
            adcIntCnt = 0;
            if (msCnt10 >= 9) {
                // LATCbits.LATC5 = ~LATCbits.LATC5;
                msCnt10 = 0;
                msFlag10 = 1;
                if (msCnt100 >= 9) {
                    // LATCbits.LATC5 = ~LATCbits.LATC5;
                    msCnt100 = 0;
                    msFlag100 = 1;
                    if (msCnt1000 >= 9) {
                        // LATCbits.LATC5 = ~LATCbits.LATC5;
                        msCnt1000 = 0;
                        msFlag1000 = 1;
                    } else {
                        msCnt1000++;
                    }
                } else {
                    msCnt100++;
                }
            } else {
                msCnt10++;
            }
        }

        // ********************************************************************
        // 10ms Tasks
        // ********************************************************************
        if (msFlag1) {
            msFlag1 = 0;
            // LATCbits.LATC5 = ~LATCbits.LATC5;

            i2cMonitor();
 
            // ****************************************************************
            // Hall simulation
            // ****************************************************************
            if (HALL_SIM_EN)
            {
                if (hallsimcnt >= HALL_SIM_MAX_CNT) {
                    hallsimcnt = 0;
                    LATCbits.LATC5 = ~LATCbits.LATC5;
                    switch (HALL_MASK) {
                        case HALL_POS_0:
                            latcSim &= ~0x01C0;
                            latcSim |= HALL_POS_60;
                            break;
                        case HALL_POS_60:
                            latcSim &= ~0x01C0;
                            latcSim |= HALL_POS_120;
                            break;
                        case HALL_POS_120:
                            latcSim &= ~0x01C0;
                            latcSim |= HALL_POS_180;
                            break;
                        case HALL_POS_180:
                            latcSim &= ~0x01C0;
                            latcSim |= HALL_POS_240;
                            break;
                        case HALL_POS_240:
                            latcSim &= ~0x01C0;
                            latcSim |= HALL_POS_300;
                            break;
                        case HALL_POS_300:
                            latcSim &= ~0x01C0;
                            latcSim |= HALL_POS_0;
                            break;
                        default:
                            latcSim = ~0x01C0;
                            latcSim |= HALL_POS_0;
                            break;
                    }
                    // get sector and speed values
                    getSpeedVals();
                } else {
                    hallsimcnt++;
                }
            }

           
            // ****************************************************************
            // End Hall simulation
            // ****************************************************************
        }
        // ********************************************************************
        // End 10ms Tasks
        // ********************************************************************

        // ********************************************************************
        // 1000ms Tasks
        // ********************************************************************
        if (msFlag1000) {
            msFlag1000 = 0;
            LED = ~LED;
        }
    }

}